<!DOCTYPE html>
<!--upload-->
<!--TODO: Make localizable somehow.-->
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>File Uploader</title>
	<style>
		body {
			font-family: system-ui, sans-serif;
			background: #e7f1ff;
			color: #333;
			padding: 2em;
			max-width: 600px;
			margin: auto;
		}

		h1 {
			text-align: center;
			color: #444;
		}

		.section {
			margin-bottom: 1em;
		}

		input[type="file"] {
			display: block;
			margin: 0.5em 0;
		}

		button {
			display: inline-block;
			padding: 0.6em 1.2em;
			font-size: 1em;
			border: none;
			border-radius: 6px;
			background-color: #4a90e2;
			color: white;
			cursor: pointer;
			transition: background 0.2s;
			margin-right: 0.5em;
		}

		#uploadBtn:enabled {
			background-color: #3aa270;
		}

		button:disabled {
			background-color: #ccc;
			cursor: not-allowed;
		}

		button:hover:not(:disabled) {
			background-color: #357ab8;
		}

		.btn {
			display: inline-block;
			padding: 0.6em 1.2em;
			font-size: 1em;
			border: none;
			border-radius: 6px;
			background-color: #4a90e2;
			color: white;
			cursor: pointer;
			transition: background 0.2s;
			margin-right: 0.5em;
		}

		.btn:hover {
			background-color: #357ab8;
		}

		#fileList {
			margin-top: 0.5em;
			font-size: 0.95em;
			color: #333;
		}

		progress {
			width: 100%;
			height: 20px;
			margin-top: 0.5em;
			display: none;
		}

		#status {
			margin-top: 0.5em;
			font-weight: 500;
		}

		#error {
			color: #d33;
			margin-top: 0.5em;
		}

		.btn input[type="file"] {
			display: none; /* hide the native control */
		}

		#resetBtn {
			display: none; /* initially hidden */
		}

		.drag-over {
			border: 2px dashed #4a90e2;
			background-color: #f0f8ff;
		}

		.drop-zone {
			border: 2px dashed #ccc;
			border-radius: 10px;
			padding: 40px 20px;
			text-align: center;
			margin: 1em 0;
			background-color: #fafafa;
			transition: all 0.3s ease;
			display: none; /* initially hidden, shown only on supported platforms */
		}

		.drop-zone-text {
			color: #666;
			font-size: 1.1em;
			margin: 0.5em 0;
		}

		.fixed-width {
			font-family: monospace;
			background: #eee;
			padding: 2px 4px;
			border-radius: 4px;
		}
	</style>
</head>
<body>
	<h1>Upload files to {{ device_name }}</h1>

	<p>Destination folder: <span class="fixed-width">{{ upload_path }}</span></p>

	<div class="section">
		<label class="btn">
			Choose individual files...
			<input type="file" id="fileInput" multiple hidden>
		</label>
		<label class="btn">
			Choose folder...
			<input type="file" id="folderInput" webkitdirectory multiple>
		</label>
		<button id="resetBtn">
			Reset
		</button>
	</div>

	<div id="dropZone" class="drop-zone">
		<div class="drop-zone-text">
			📁 Drop files here or use the buttons above
		</div>
	</div>

	<div id="fileList"></div>

	<div id="uploadedSection" style="display: none;">
		<h3>Uploaded Files:</h3>
		<div id="uploadedList"></div>
	</div>

	<div class="section">
		<button id="uploadBtn" disabled>Start upload!</button>
	</div>

	<progress id="progressBar" value="0" max="100"></progress>
	<div id="status"></div>
	<div id="error"></div>

	<script>
		(() => {
			const fileInput = document.getElementById("fileInput");
			const folderInput = document.getElementById("folderInput");
			const uploadBtn = document.getElementById("uploadBtn");
			const resetBtn = document.getElementById("resetBtn");
			const fileListDiv = document.getElementById("fileList");
			const uploadedSection = document.getElementById("uploadedSection");
			const uploadedListDiv = document.getElementById("uploadedList");
			const dropZone = document.getElementById("dropZone");
			const progressBar = document.getElementById("progressBar");
			const statusDiv = document.getElementById("status");
			const errorDiv = document.getElementById("error");

			let files = [];
			let uploadedFiles = [];
			let droppedFiles = [];

			// Feature detection for drag and drop support
			function isDragDropSupported() {
				// Check for basic drag and drop API support
				const div = document.createElement('div');
				const hasBasicSupport = ('draggable' in div) && ('ondrop' in div);

				// Check if it's a mobile device (where drag/drop from file system is limited)
				const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

				// Check if it's a touch-only device
				const isTouchOnly = ('ontouchstart' in window) && !window.matchMedia('(pointer: fine)').matches;

				return hasBasicSupport && !isMobile && !isTouchOnly;
			}

			// Show drop zone only if drag and drop is supported
			if (isDragDropSupported()) {
				dropZone.style.display = 'block';
			}

			function formatBytes(bytes, decimals = 2) {
				if (bytes === 0) return '0 B';
				const k = 1024;
				const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
				const i = Math.floor(Math.log(bytes) / Math.log(k));
				const size = parseFloat((bytes / Math.pow(k, i)).toFixed(decimals));
				return `${size} ${units[i]}`;
			}

			function updateUploadedList() {
				uploadedListDiv.innerHTML = "";
				if (uploadedFiles.length > 0) {
					uploadedSection.style.display = "block";
					const list = document.createElement("ul");
					uploadedFiles.forEach(f => {
						const li = document.createElement("li");
						const formattedBytes = formatBytes(f.size, 2);
						const name = f.webkitRelativePath || f.name;
						li.textContent = `${name} (${formattedBytes}) - ✓ Uploaded`;
						li.style.color = "#2d7a2d";
						list.appendChild(li);
					});
					uploadedListDiv.appendChild(list);
				} else {
					uploadedSection.style.display = "none";
				}
			}

			function updateFileList() {
				files = [...fileInput.files, ...folderInput.files, ...droppedFiles];
				fileListDiv.innerHTML = "";
				if (files.length > 0) {
					uploadBtn.disabled = false;
					resetBtn.style.display = "inline-block";
					const list = document.createElement("ul");
					files.forEach(f => {
						const li = document.createElement("li");
						const formattedBytes = formatBytes(f.size, 2);
						const name = f.webkitRelativePath || f.name;
						li.textContent = `${name} (${formattedBytes} bytes)`;
						list.appendChild(li);
					});
					fileListDiv.appendChild(list);
				} else {
					uploadBtn.disabled = true;
					resetBtn.style.display = "none";
				}
			}

			fileInput.addEventListener("change", updateFileList);
			folderInput.addEventListener("change", updateFileList);

			// Drag and drop functionality
			dropZone.addEventListener("dragover", (e) => {
				e.preventDefault();
				dropZone.classList.add("drag-over");
			});

			dropZone.addEventListener("dragleave", (e) => {
				e.preventDefault();
				dropZone.classList.remove("drag-over");
			});

			dropZone.addEventListener("drop", (e) => {
				e.preventDefault();
				dropZone.classList.remove("drag-over");

				const dt = e.dataTransfer;
				const allFiles = Array.from(dt.files);

				// Filter out zero-byte entries (usually folders or invalid entries)
				const validFiles = allFiles.filter(file => file.size > 0);

				// Show a message if some files were filtered out
				if (allFiles.length > validFiles.length) {
					const filteredCount = allFiles.length - validFiles.length;
					statusDiv.textContent = `Note: ${filteredCount} folder(s) or empty file(s) were skipped. Only files can be drag/dropped.`;
					setTimeout(() => {
						if (statusDiv.textContent.includes("folder(s) or empty file(s) were skipped")) {
							statusDiv.textContent = "";
						}
					}, 8000);
				}

				// Add valid dropped files to the existing array
				droppedFiles = [...droppedFiles, ...validFiles];
				updateFileList();
			});

			// Also handle drag/drop on the entire document to prevent browser default behavior
			document.addEventListener("dragover", (e) => {
				e.preventDefault();
			});

			document.addEventListener("drop", (e) => {
				e.preventDefault();
			});

			resetBtn.addEventListener("click", () => {
				// Clear the file inputs
				fileInput.value = "";
				folderInput.value = "";
				// Clear all arrays and update displays
				files = [];
				droppedFiles = [];
				uploadedFiles = [];
				updateFileList();
				updateUploadedList();
			});

			uploadBtn.addEventListener("click", async () => {
				if (files.length === 0) return;

				uploadBtn.disabled = true;
				errorDiv.textContent = "";
				statusDiv.textContent = "";
				progressBar.style.display = "block";
				progressBar.value = 0;

				const filesToUpload = [...files]; // Create a copy to iterate over

				// Clear all file sources so files disappear from pending list as they upload
				fileInput.value = "";
				folderInput.value = "";
				droppedFiles = [];
				files = [];

				for (let i = 0; i < filesToUpload.length; i++) {
					const file = filesToUpload[i];
					statusDiv.textContent = `Uploading ${file.webkitRelativePath || file.name} (${i + 1}/${filesToUpload.length})`;

					try {
						await uploadFile(file);
						// Move successfully uploaded file to uploaded list
						uploadedFiles.push(file);
						updateUploadedList();
					} catch (err) {
						// If upload fails, add remaining files back to pending list
						files = filesToUpload.slice(i);
						updateFileList();
						errorDiv.textContent = err.message;
						progressBar.style.display = "none";
						uploadBtn.disabled = false;
						return;
					}
				}

				// Update the pending files list (should be empty now)
				updateFileList();
				statusDiv.textContent = "All files uploaded successfully.";
				progressBar.style.display = "none";
				// Note: uploadBtn state is managed by updateFileList() - disabled when no files
			});

			function uploadFile(file) {
				return new Promise((resolve, reject) => {
					const xhr = new XMLHttpRequest();
					xhr.open("POST", "/upload_file");

					// Add custom metadata headers if needed:
					xhr.setRequestHeader("X-Client-Version", "1.0");
					xhr.setRequestHeader("X-Upload-Timestamp", new Date().toISOString());
					xhr.setRequestHeader("X-File-Size", file.size.toString());

					xhr.upload.onprogress = e => {
						if (e.lengthComputable) {
							progressBar.value = (e.loaded / e.total) * 100;
						}
					};

					xhr.onload = () => {
						if (xhr.status >= 200 && xhr.status < 300) {
							resolve();
						} else {
							let msg;
							switch (xhr.status) {
								case 400: msg = "Malformed request (boundary or headers invalid)."; break;
								case 500: msg = "Target is probably out of disk space."; break;
								default: msg = `Upload failed with status ${xhr.status}.`; break;
							}
							reject(new Error(msg));
						}
					};

					xhr.onerror = () => reject(new Error("Connection error during upload."));

					// Try to preserve any directory structure, if supported.
					const formData = new FormData();
					formData.append("file", file, file.webkitRelativePath || file.name);
					xhr.send(formData);
				});
			}
		})();
	</script>
</body>
</html>
